package WebCrawler

import (
	"fmt"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Uuid"
	"github.com/PuerkitoBio/goquery"
	"io"
	"net/http"
	"strings"
	"time"
)

type httpGet struct {
}

func (e *httpGet) HttpRequest(url string, header map[string]string, timeout, try int) (*goquery.Document, error) {
	// 第一次查询
	doc, err := e.tryRequest(url, header, timeout)
	if err == nil {
		return doc, nil
	}
	if err.Error() == "请求失败，状态码：404" {
		return doc, err
	}

	// 重试
	for i := 0; i < try; i++ {
		doc, err = e.tryRequest(url, header, timeout)
		if err != nil {
			continue
		}

		return doc, err
	}

	return nil, err
}

func (e *httpGet) HttpRequestRandomUserAgent(url string, header map[string]string, timeout, try int) (*goquery.Document, error) {
	if header == nil {
		header = make(map[string]string)
	}

	// 第一次查询
	header["User-Agent"] = "PostmanRuntime/" + Uuid.RandomUUID()
	doc, err := e.tryRequest(url, header, timeout)
	if err == nil {
		return doc, nil
	}
	if err.Error() == "请求失败，状态码：404" {
		return doc, err
	}

	// 重试
	for i := 0; i < try; i++ {
		header["User-Agent"] = "PostmanRuntime/" + Uuid.RandomUUID()
		doc, err = e.tryRequest(url, header, timeout)
		if err != nil {
			continue
		}

		return doc, err
	}

	return nil, err
}

func (e *httpGet) tryRequest(url string, header map[string]string, timeout int) (*goquery.Document, error) {
	// 创建一个新的http.Request对象
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}

	for k, v := range header {
		req.Header.Set(k, v)
	}

	client := http.DefaultClient
	client.Timeout = time.Duration(timeout) * time.Second

	// 使用http.DefaultClient发送请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("请求失败，状态码：%d", resp.StatusCode)
	}

	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, err
	}

	return doc, nil
}

func (e *httpGet) tryGet(url string, timeout int) (*goquery.Document, error) {
	client := http.DefaultClient
	client.Timeout = time.Duration(timeout) * time.Second

	resp, err := client.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("请求失败，状态码：%d", resp.StatusCode)
	}

	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, err
	}

	return doc, nil
}

func (e *httpGet) HttpGet(url string, timeout, try int) (*goquery.Document, error) {
	// 第一次查询
	doc, err := e.tryGet(url, timeout)
	if err == nil {
		return doc, nil
	}

	// 重试
	for i := 0; i < try; i++ {
		doc, err = e.tryGet(url, timeout)
		if err != nil {
			continue
		}

		return doc, err
	}

	return nil, err
}

func (e *httpGet) tryGetBin(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("请求失败，状态码：%d", resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

func (e *httpGet) HttpGetBin(url string, try int) ([]byte, error) {
	// 第一次查询
	bin, err := e.tryGetBin(url)
	if err == nil {
		return bin, nil
	}

	// 重试
	for i := 0; i < try; i++ {
		bin, err = e.tryGetBin(url)
		if err != nil {
			continue
		}

		return bin, err
	}

	return nil, err
}

func (e *httpGet) MakeUrl(host, url string) string {
	href := ""
	if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
		href = url
	} else if strings.HasPrefix(url, "/") {
		href = host + url
	} else {
		href = host + "/" + url
	}

	return href
}
